'\" te
.\" Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd. All Rights Reserved.
.\" Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
.\" "Software"), to deal in the Software without restriction, including
.\" without limitation the rights to use, copy, modify, merge, publish,
.\" distribute, and/or sell copies of the Software, and to permit persons
.\" to whom the Software is furnished to do so, provided that the above
.\" copyright notice(s) and this permission notice appear in all copies of
.\" the Software and that both the above copyright notice(s) and this
.\" permission notice appear in supporting documentation.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\" Except as contained in this notice, the name of a copyright holder
.\" shall not be used in advertising or otherwise to promote the sale, use
.\" or other dealings in this Software without prior written authorization
.\" of the copyright holder.
.\" Portions Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
.TH PCA_LOOKUP_FILE 3TECLA "January 18, 2020"
.SH NAME
pca_lookup_file, del_PathCache, del_PcaPathConf, new_PathCache,
new_PcaPathConf, pca_last_error, pca_path_completions, pca_scan_path,
pca_set_check_fn, ppc_file_start, ppc_literal_escapes \- lookup a file in a
list of directories
.SH SYNOPSIS
.nf
cc [ \fIflag\fR\&.\|.\|. ] \fIfile\fR\&.\|.\|. \fB-ltecla\fR [ \fIlibrary\fR\&.\|.\|. ]
#include <libtecla.h>

\fBchar *\fR\fBpca_lookup_file\fR(\fBPathCache *\fR\fIpc\fR, \fBconst char *\fR\fIname\fR,
     \fBint\fR \fIname_len\fR, \fBint\fR \fIliteral\fR);
.fi

.LP
.nf
\fBPathCache *\fR\fBdel_PathCache\fR(\fBPathCache *\fR\fIpc\fR);
.fi

.LP
.nf
\fBPcaPathConf *\fR\fBdel_PcaPathConf\fR(\fBPcaPathConf *\fR\fIppc\fR);
.fi

.LP
.nf
\fBPathCache *\fR\fBnew_PathCache\fR(\fBvoid\fR);
.fi

.LP
.nf
\fBPcaPathConf *\fR\fBnew_PcaPathConf\fR(\fBPathCache *\fR\fIpc\fR);
.fi

.LP
.nf
\fBconst char *\fR\fBpca_last_error\fR(\fBPathCache *\fR\fIpc\fR);
.fi

.LP
.nf
\fBCPL_MATCH_FN\fR(\fBpca_path_completions\fR);
.fi

.LP
.nf
\fBint\fR \fBpca_scan_path\fR(\fBPathCache *\fR\fIpc\fR, \fBconst char *\fR\fIpath\fR);
.fi

.LP
.nf
\fBvoid\fR \fBpca_set_check_fn\fR(\fBPathCache *\fR\fIpc\fR, \fBCplCheckFn *\fR\fIcheck_fn\fR,
     \fBvoid *\fR\fIdata\fR);
.fi

.LP
.nf
\fBvoid\fR \fBppc_file_start\fR(\fBPcaPathConf *\fR\fIppc\fR, \fBint\fR \fIstart_index\fR);
.fi

.LP
.nf
\fBvoid\fR \fBppc_literal_escapes\fR(\fBPcaPathConf *\fR\fIppc\fR, \fBint\fR \fIliteral\fR);
.fi

.SH DESCRIPTION
The \fBPathCache\fR object is part of the \fBlibtecla\fR(3LIB) library.
\fBPathCache\fR objects allow an application to search for files in any colon
separated list of directories, such as the UNIX execution \fBPATH\fR
environment variable. Files in absolute directories are cached in a
\fBPathCache\fR object, whereas relative directories are scanned as needed.
Using a \fBPathCache\fR object, you can look up the full pathname of a simple
filename, or you can obtain a list of the possible completions of a given
filename prefix. By default all files in the list of directories are targets
for lookup and completion, but a versatile mechanism is provided for only
selecting specific types of files. The obvious application of this facility is
to provide Tab-completion and lookup of executable commands in the UNIX
\fBPATH\fR, so an optional callback which rejects all but executable files is
provided.
.SS "An Example"
Under UNIX, the following example program looks up and displays the full
pathnames of each of the command names on the command line.
.sp
.in +2
.nf
#include <stdio.h>
#include <stdlib.h>
#include <libtecla.h>

int main(int argc, char *argv[])
{
        int i;
        /*
        * Create a cache for executable files.
        */
        PathCache *pc = new_PathCache();
        if(!pc)
          exit(1);
        /*
        * Scan the user's PATH for executables.
        */
        if(pca_scan_path(pc, getenv("PATH"))) {
          fprintf(stderr, "%s\en", pca_last_error(pc));
          exit(1);
        }
        /*
        * Arrange to only report executable files.
        */
        pca_set_check_fn(pc, cpl_check_exe, NULL);
        /*
        * Lookup and display the full pathname of each of the
        * commands listed on the command line.
        */
        for(i=1; i<argc; i++) {
          char *cmd = pca_lookup_file(pc, argv[i], -1, 0);
          printf("The full pathname of '%s' is %s\e\en", argv[i],
                 cmd ? cmd : "unknown");
        }
        pc = del_PathCache(pc);  /* Clean up */
        return 0;
}
.fi
.in -2

.sp
.LP
The following is an example of what this does on a laptop under LINUX:
.sp
.in +2
.nf
$ ./example less more blob
The full pathname of 'less' is /usr/bin/less
The full pathname of 'more' is /bin/more
The full pathname of 'blob' is unknown
$
.fi
.in -2

.SS "Function Descriptions"
To use the facilities of this module, you must first allocate a \fBPathCache\fR
object by calling the \fBnew_PathCache()\fR constructor function. This function
creates the resources needed to cache and lookup files in a list of
directories. It returns \fINULL\fR on error.
.SS "Populating The Cache"
Once you have created a cache, it needs to be populated with files. To do this,
call the \fBpca_scan_path()\fR function. Whenever this function is called, it
discards the current contents of the cache, then scans the list of directories
specified in its path argument for files. The path argument must be a string
containing a colon-separated list of directories, such as
"\fB/usr/bin\fR:\fB/home/mcs/bin\fR:". This can include directories specified
by absolute pathnames such as "\fB/usr/bin\fR", as well as sub-directories
specified by relative pathnames such as "." or "\fBbin\fR". Files in the
absolute directories are immediately cached in the specified \fBPathCache\fR
object, whereas subdirectories, whose identities obviously change whenever the
current working directory is changed, are marked to be scanned on the fly
whenever a file is looked up.
.sp
.LP
On success this function return 0. On error it returns 1, and a description of
the error can be obtained by calling \fBpca_last_error\fR(\fIpc\fR).
.SS "Looking Up Files"
Once the cache has been populated with files, you can look up the full pathname
of a file, simply by specifying its filename to \fBpca_lookup_file()\fR.
.sp
.LP
To make it possible to pass this function a filename which is actually part of
a longer string, the \fIname_len\fR argument can be used to specify the length
of the filename at the start of the \fIname\fR[] argument. If you pass -1 for
this length, the length of the string will be determined with \fIstrlen\fR. If
the \fIname\fR[] string might contain backslashes that escape the special
meanings of spaces and tabs within the filename, give the \fIliteral\fR
argument the value 0. Otherwise, if backslashes should be treated as normal
characters, pass 1 for the value of the \fIliteral\fR argument.
.SS "Filename Completion"
Looking up the potential completions of a filename-prefix in the filename cache
is achieved by passing the provided \fBpca_path_completions()\fR callback
function to the \fBcpl_complete_word\fR(3TECLA) function.
.sp
.LP
This callback requires that its data argument be a pointer to a PcaPathConf
object. Configuration objects of this type are allocated by calling
\fBnew_PcaPathConf()\fR.
.sp
.LP
This function returns an object initialized with default configuration
parameters, which determine how the \fBcpl_path_completions()\fR callback
function behaves. The functions which allow you to individually change these
parameters are discussed below.
.sp
.LP
By default, the \fBpca_path_completions()\fR callback function searches
backwards for the start of the filename being completed, looking for the first
un-escaped space or the start of the input line. If you wish to specify a
different location, call \fBppc_file_start()\fR with the index at which the
filename starts in the input line. Passing \fIstart_index\fR=-1 re-enables the
default behavior.
.sp
.LP
By default, when \fBpca_path_completions()\fR looks at a filename in the input
line, each lone backslash in the input line is interpreted as being a special
character which removes any special significance of the character which follows
it, such as a space which should be taken as part of the filename rather than
delimiting the start of the filename. These backslashes are thus ignored while
looking for completions, and subsequently added before spaces, tabs and literal
backslashes in the list of completions. To have unescaped backslashes treated
as normal characters, call \fBppc_literal_escapes()\fR with a non-zero value in
its literal argument.
.sp
.LP
When you have finished with a \fBPcaPathConf\fR variable, you can pass it to
the \fBdel_PcaPathConf()\fR destructor function to reclaim its memory.
.SS "Being Selective"
If you are only interested in certain types or files, such as, for example,
executable files, or files whose names end in a particular suffix, you can
arrange for the file completion and lookup functions to be selective in the
filenames that they return. This is done by registering a callback function
with your \fBPathCache\fR object. Thereafter, whenever a filename is found
which either matches a filename being looked up or matches a prefix which is
being completed, your callback function will be called with the full pathname
of the file, plus any application-specific data that you provide. If the
callback returns 1 the filename will be reported as a match. If it returns 0,
it will be ignored. Suitable callback functions and their prototypes should be
declared with the following macro. The \fBCplCheckFn\fR typedef is also
provided in case you wish to declare pointers to such functions.
.sp
.in +2
.nf
#define CPL_CHECK_FN(fn) int (fn)(void *data, const char *pathname)
typedef CPL_CHECK_FN(CplCheckFn);
.fi
.in -2

.sp
.LP
Registering one of these functions involves calling the
\fBpca_set_check_fn()\fR function. In addition to the callback function passed
with the \fIcheck_fn\fR argument, you can pass a pointer to anything with the
\fIdata\fR argument. This pointer will be passed on to your callback function
by its own \fIdata\fR argument whenever it is called, providing a way to pass
application-specific data to your callback. Note that these callbacks are
passed the full pathname of each matching file, so the decision about whether a
file is of interest can be based on any property of the file, not just its
filename. As an example, the provided \fBcpl_check_exe()\fR callback function
looks at the executable permissions of the file and the permissions of its
parent directories, and only returns 1 if the user has execute permission to
the file. This callback function can thus be used to lookup or complete command
names found in the directories listed in the user's \fBPATH\fR environment
variable. The example program above provides a demonstration of this.
.sp
.LP
Beware that if somebody tries to complete an empty string, your callback will
get called once for every file in the cache, which could number in the
thousands. If your callback does anything time consuming, this could result in
an unacceptable delay for the user, so callbacks should be kept short.
.sp
.LP
To improve performance, whenever one of these callbacks is called, the choice
that it makes is cached, and the next time the corresponding file is looked up,
instead of calling the callback again, the cached record of whether it was
accepted or rejected is used. Thus if somebody tries to complete an empty
string, and hits tab a second time when nothing appears to happen, there will
only be one long delay, since the second pass will operate entirely from the
cached dispositions of the files. These cached dispositions are discarded
whenever \fBpca_scan_path()\fR is called, and whenever \fBpca_set_check_fn()\fR
is called with changed callback function or \fIdata\fR arguments.
.SS "Error Handling"
If \fBpca_scan_path()\fR reports that an error occurred by returning 1, you can
obtain a terse description of the error by calling
\fBpca_last_error\fR(\fIpc\fR). This returns an internal string containing an
error message.
.SS "Cleaning Up"
Once you have finished using a \fBPathCache\fR object, you can reclaim its
resources by passing it to the \fBdel_PathCache()\fR destructor function. This
takes a pointer to one of these objects, and always returns \fINULL\fR.
.SS "Thread Safety"
It is safe to use the facilities of this module in multiple threads, provided
that each thread uses a separately allocated \fBPathCache\fR object. In other
words, if two threads want to do path searching, they should each call
\fBnew_PathCache()\fR to allocate their own caches.
.SH ATTRIBUTES
See \fBattributes\fR(7) for descriptions of the following attributes:
.sp

.sp
.TS
box;
c | c
l | l .
ATTRIBUTE TYPE	ATTRIBUTE VALUE
_
Interface Stability	Evolving
_
MT-Level	MT-Safe
.TE

.SH SEE ALSO
.BR libtecla (3LIB),
.BR cpl_complete_word (3TECLA),
.BR ef_expand_file (3TECLA),
.BR gl_get_line (3TECLA),
.BR attributes (7)
